package unimelb.distSystems.game.players;

import unimelb.distSystems.game.tools.CustomGeometry;

import com.jme3.asset.AssetManager;
import com.jme3.bounding.BoundingBox;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.control.VehicleControl;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;

public abstract class PlayerCar {
	protected long player_id;
	protected VehicleControl player_control;
	protected Node carNode;
	protected CustomGeometry geo_tool;
	protected float wheelRadius;
	
	public PlayerCar(long player_id)
	{
		this.player_id=player_id;
	}
	
	public void buildPlayer(AssetManager assetManager, Node rootNode, BulletAppState bulletAppState,String car_type) {
        float stiffness = 100.0f;//200=f1 car
        float compValue = 1f; //(lower than damp!)
        float dampValue = 1.1f;
        final float mass = 600;
        
        geo_tool=new CustomGeometry();

        //Load model and get chassis Geometry
        carNode = (Node)assetManager.loadModel("Models/cars/"+car_type+".scene");
        carNode.setShadowMode(ShadowMode.Cast);
        Geometry chasis = geo_tool.findGeom(carNode, car_type);
        BoundingBox box = (BoundingBox) chasis.getModelBound();

        //Create a hull collision shape for the chassis
        CollisionShape carHull = CollisionShapeFactory.createDynamicMeshShape(chasis);

        //Create a vehicle control
        player_control = new VehicleControl(carHull, mass);
        carNode.addControl(player_control);

        //Setting default values for wheels
        player_control.setSuspensionCompression(compValue * 2.0f * FastMath.sqrt(stiffness));
        player_control.setSuspensionDamping(dampValue * 2.0f * FastMath.sqrt(stiffness));
        player_control.setSuspensionStiffness(stiffness);
        player_control.setMaxSuspensionForce(10000);

        //Create four wheels and add them at their locations
        //note that our fancy car actually goes backwards..
        Vector3f wheelDirection = new Vector3f(0, -1, 0);
        Vector3f wheelAxle = new Vector3f(-1, 0, 0);

        Geometry wheel_fr = geo_tool.findGeom(carNode, "WheelFrontRight");
        wheel_fr.center();
        box = (BoundingBox) wheel_fr.getModelBound();
        wheelRadius = box.getYExtent();
        float back_wheel_h = (wheelRadius * 1.7f) - 1f;
        float front_wheel_h = (wheelRadius * 1.9f) - 1f;
        player_control.addWheel(wheel_fr.getParent(), box.getCenter().add(0, -front_wheel_h, 0),
                wheelDirection, wheelAxle, 0.2f, wheelRadius, true);

        Geometry wheel_fl = geo_tool.findGeom(carNode, "WheelFrontLeft");
        wheel_fl.center();
        box = (BoundingBox) wheel_fl.getModelBound();
        player_control.addWheel(wheel_fl.getParent(), box.getCenter().add(0, -front_wheel_h, 0),
                wheelDirection, wheelAxle, 0.2f, wheelRadius, true);

        Geometry wheel_br = geo_tool.findGeom(carNode, "WheelBackRight");
        wheel_br.center();
        box = (BoundingBox) wheel_br.getModelBound();
        player_control.addWheel(wheel_br.getParent(), box.getCenter().add(0, -back_wheel_h, 0),
                wheelDirection, wheelAxle, 0.2f, wheelRadius, false);

        Geometry wheel_bl = geo_tool.findGeom(carNode, "WheelBackLeft");
        wheel_bl.center();
        box = (BoundingBox) wheel_bl.getModelBound();
        player_control.addWheel(wheel_bl.getParent(), box.getCenter().add(0, -back_wheel_h, 0),
                wheelDirection, wheelAxle, 0.2f, wheelRadius, false);

        player_control.getWheel(2).setFrictionSlip(4);
        player_control.getWheel(3).setFrictionSlip(4);

        rootNode.attachChild(carNode);
        bulletAppState.getPhysicsSpace().add(player_control);
        
    }
	
	public void locate(Vector3f location, Quaternion rotation)
    {
		player_control.setPhysicsLocation(location);
		player_control.setPhysicsRotation(rotation);
		//player_control.setPhysicsRotation(new Quaternion(0f, 0f, 0f, 1f));
    }
	
	public VehicleControl getPlayer()
    {
		return player_control;
    }
    
    public Node getCarNode()
    {
		return carNode;
    }

    public long getPlayer_id() {
        return player_id;
    }

    public void setPlayer_id(long player_id) {
        this.player_id = player_id;
    }

    
}
